#include "Texture2D.h"

namespace egg{

    Texture2D::Texture2D(const Image2D& _img):
    Texture(GL_TEXTURE_2D),
    mPixelFormat(_img.mFormat),
    mDevicePixelFormat(_img.mFormat){
        glGenTextures(1,&mID);
        GraphicDevice_CatchError;
        innerBuild(_img.mWidth,_img.mHeight,_img.mPixels);
    }

    Texture2D::Texture2D(PixelFormat _format,uint32 _w,uint32 _h):
    Texture(GL_TEXTURE_2D),
    mPixelFormat(_format),
    mDevicePixelFormat(_format){
        glGenTextures(1,&mID);
        GraphicDevice_CatchError;
        innerBuild(_w,_h,0);
    }

    Texture2D::~Texture2D(){
        glDeleteTextures(1, &mID);
        GraphicDevice_CatchError;
    }

    void Texture2D::resize(uint32 _w,uint32 _h){
        if(mWidth!=_w||mHeight!=_h){
            innerBuild(_w,_h,0);
        }
    }

    void Texture2D::writePixels(const void* _data){
        glBindTexture(GL_TEXTURE_2D,mID);
        glTexSubImage2D(
            GL_TEXTURE_2D, 0, 0, 0, 
            mWidth, mHeight, 
            mDevicePixelFormat.mFormat, 
            mDevicePixelFormat.mType,
            _data);
        glBindTexture(GL_TEXTURE_2D,0);
        GraphicDevice_CatchError;
    }

    void Texture2D::readPixels(void* _dest){
        glBindTexture(GL_TEXTURE_2D,mID);
        glGetTexImage(
            GL_TEXTURE_2D, 0, 
            mDevicePixelFormat.mFormat, 
            mDevicePixelFormat.mType,
            _dest);
        glBindTexture(GL_TEXTURE_2D,0);
        GraphicDevice_CatchError;
    }

    void Texture2D::innerBuild(uint32 _w,uint32 _h,const void* _pixels){
        mWidth=_w;
        mHeight=_h;
        if(_pixels)
            mNeedMipMap=true;
        else
            mNeedMipMap=false;
        glBindTexture(GL_TEXTURE_2D,mID);
        if(mNeedMipMap){
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            gluBuild2DMipmaps(
                GL_TEXTURE_2D,
                mDevicePixelFormat.mInnerFormat,
                mWidth,mHeight,
                mDevicePixelFormat.mFormat,
                mDevicePixelFormat.mType,
                _pixels);
            GraphicDevice_CatchError;
        }else{
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            if(mDevicePixelFormat.mFormat==PF_Depth24Stencil8){
                glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
            }
            glTexImage2D(
                GL_TEXTURE_2D,0,
                mDevicePixelFormat.mInnerFormat,
                mWidth,mHeight,0,
                mDevicePixelFormat.mFormat,
                mDevicePixelFormat.mType,
                0);
            GraphicDevice_CatchError;
        }
        glBindTexture(GL_TEXTURE_2D,0);
        GraphicDevice_CatchError;
    }

}